--[[ FlyoutArrowButton ]]

local ARROW_BUTTON_DEF_WIDTH = 36
local ACCEPTABLE_COMMANDS = {
	["spell"] = true,
	["item"] = true,
	["macro"] = true,
	["companion"] = true,
	["equipmentset"] = true
}
FlyoutArrowButton = {}


local ArrowButtonOnClickSnippet = [=[
	local B_PLACE_SIZE = 36
	local B_PLACE_OFFSET = 4

	local D_UP		= 1
	local D_LEFT	= 2
	local D_DOWN	= 3
	local D_RIGHT	= 4

	if button == "LeftButton" then
		lfRef = self:GetFrameRef("FlyoutListFrame_Ref")
		
		local width = B_PLACE_SIZE + 2 * B_PLACE_OFFSET
		local height = self:GetAttribute("bcount") * (B_PLACE_SIZE + B_PLACE_OFFSET) + B_PLACE_OFFSET
		
		if self:GetAttribute("expandDir") == D_UP or self:GetAttribute("expandDir") == D_DOWN then
			lfRef:SetWidth(width)
			lfRef:SetHeight(height)
		else
			lfRef:SetWidth(height)
			lfRef:SetHeight(width)
		end

		if self:GetAttribute("expanded") then
			self:SetAttribute("expanded", false)
			lfRef:Hide()
		else
			--close other opened lists
			local stub = self:GetFrameRef("StubFrame")
			if stub and stub:GetAttribute("unique-list") then
				local count = stub:GetAttribute("ArrowButtonsCount")
				if count then
					for i = 1, count do
						local ab = stub:GetFrameRef("FbcArrowButtons"..i)
						if ab and ab:GetAttribute("expanded") then
							local lf = ab:GetFrameRef("FlyoutListFrame_Ref")
							if lf then
								ab:SetAttribute("expanded", false)
								lf:Hide()
							end
						end
					end
				end
			end
			
			self:SetAttribute("expanded", true)
			lfRef:Show()
		end
	end
]=]

ArrowButtonOnEnterSnippet = [=[
	if not(self:GetAttribute("mouseoverincombat")) and (self:GetAttribute("incombat") > 0) then
		return
	end
	
	local B_PLACE_SIZE = 36
	local B_PLACE_OFFSET = 4

	local D_UP		= 1
	local D_LEFT	= 2
	local D_DOWN	= 3
	local D_RIGHT	= 4

	lfRef = self:GetFrameRef("FlyoutListFrame_Ref")
	
	local width = B_PLACE_SIZE + 2 * B_PLACE_OFFSET
	local height = self:GetAttribute("bcount") * (B_PLACE_SIZE + B_PLACE_OFFSET) + B_PLACE_OFFSET
	
	if self:GetAttribute("expandDir") == D_UP or self:GetAttribute("expandDir") == D_DOWN then
		lfRef:SetWidth(width)
		lfRef:SetHeight(height)
	else
		lfRef:SetWidth(height)
		lfRef:SetHeight(width)
	end

	if self:GetAttribute("expanded") then
		self:SetAttribute("expanded", false)
		lfRef:Hide()
	else
		--close other opened lists
		local stub = self:GetFrameRef("StubFrame")
		if stub and stub:GetAttribute("unique-list") then
			local count = stub:GetAttribute("ArrowButtonsCount")
			if count then
				for i = 1, count do
					local ab = stub:GetFrameRef("FbcArrowButtons"..i)
					if ab and ab:GetAttribute("expanded") then
						local lf = ab:GetFrameRef("FlyoutListFrame_Ref")
						if lf then
							ab:SetAttribute("expanded", false)
							lf:Hide()
						end
					end
				end
			end
		end
		
		self:SetAttribute("expanded", true)
		lfRef:Show()
	end
]=]

local ArrowButtonCombatSnippet = [=[
	if newstate == 1 and self:GetAttribute("bcount") == 0 and self:IsVisible() then
		self:SetAttribute("expanded", false)
		self:Hide()
	end
	self:SetAttribute("incombat", newstate)
]=]

local ArrowButtonVehicleSnippet = [=[
	if newstate == 1 and self:IsVisible() then
		self:SetAttribute("was_visible_vehicle", true)
		self:SetAttribute("expanded", false)
		self:Hide()
	elseif self:GetAttribute("was_visible_vehicle") then
		self:SetAttribute("was_visible_vehicle", false)
		self:SetAttribute("expanded", true)
		self:Show()
	end
]=]

function FlyoutArrowButton:SetTextureRotation(expandDir, expanded)
	if expanded then
		if expandDir == FBC_DIR_UP then
			SetClampedTextureRotation(self.FlyoutArrow, 180)
		elseif expandDir == FBC_DIR_LEFT then
			SetClampedTextureRotation(self.FlyoutArrow, 90)
		elseif expandDir == FBC_DIR_DOWN then
			SetClampedTextureRotation(self.FlyoutArrow, 0)
		else --if expandDir == FBC_DIR_RIGHT then
			SetClampedTextureRotation(self.FlyoutArrow, 270)
		end
	else
		if expandDir == FBC_DIR_UP then
			SetClampedTextureRotation(self.FlyoutArrow, 0)
		elseif expandDir == FBC_DIR_LEFT then
			SetClampedTextureRotation(self.FlyoutArrow, 270)
		elseif expandDir == FBC_DIR_DOWN then
			SetClampedTextureRotation(self.FlyoutArrow, 180)
		else --if expandDir == FBC_DIR_RIGHT then
			SetClampedTextureRotation(self.FlyoutArrow, 90)
		end
	end
end

function FlyoutArrowButton:SetFrameSize(expandDir)
	if expandDir == FBC_DIR_UP or expandDir == FBC_DIR_DOWN then
		self:SetWidth(ARROW_BUTTON_DEF_WIDTH)
		self:SetHeight(FbcArrowButtonsHeight)
	else
		self:SetWidth(FbcArrowButtonsHeight)
		self:SetHeight(ARROW_BUTTON_DEF_WIDTH)
	end
end

function FlyoutArrowButton:SetAnchor(parent, expandDir)
	self:ClearAllPoints()
	self.FlyoutArrow:ClearAllPoints()
	if expandDir == FBC_DIR_UP then
		self:SetPoint("TOP", parent, "TOP", 0, FBC_ARROW_OFFSET)
		self.FlyoutArrow:SetPoint("TOP")
	elseif expandDir == FBC_DIR_LEFT then
		self:SetPoint("LEFT", parent, "LEFT", -FBC_ARROW_OFFSET, 0)
		self.FlyoutArrow:SetPoint("LEFT")
	elseif expandDir == FBC_DIR_DOWN then
		self:SetPoint("BOTTOM", parent, "BOTTOM", 0, -FBC_ARROW_OFFSET)
		self.FlyoutArrow:SetPoint("BOTTOM")
	else
		self:SetPoint("RIGHT", parent, "RIGHT", FBC_ARROW_OFFSET, 0)
		self.FlyoutArrow:SetPoint("RIGHT")
	end
end

function FlyoutArrowButton:SetHighlight(value)
	if value then
		self:SetHighlightTexture("Interface\\Buttons\\CheckButtonHilight", "ADD")
	else
		self:SetHighlightTexture("")
	end
end

function FlyoutArrowButton_New(parent)
	parent.customFlyout = true
	local actnBtnName = parent:GetName()
	local tempFrame = _G[actnBtnName.."ArrowBtn"]

	local arrowBtn
	if tempFrame then
		FbcArrowButtons[actnBtnName] = tempFrame --reuse frame
		arrowBtn = FbcArrowButtons[actnBtnName]
	else
		FbcArrowButtons[actnBtnName] = CreateFrame("CheckButton", actnBtnName.."ArrowBtn", parent, "CustomFlyoutArrowButtonTemplate")
		arrowBtn = FbcArrowButtons[actnBtnName]
		
		-- adding methods to arrow button
		for k, v in pairs(FlyoutArrowButton) do
			if type(v) == "function" then
				arrowBtn[k] = v
			end
		end
		
		--set reference in stub
		local count = FbcStubFrame:GetAttribute("ArrowButtonsCount")
		if not(count) then
			count = 1
		else
			count = count + 1
		end
		FbcStubFrame:SetAttribute("ArrowButtonsCount", count)
		FbcStubFrame:SetFrameRef("FbcArrowButtons"..count, arrowBtn)
		arrowBtn:SetFrameRef("StubFrame", FbcStubFrame)
		arrowBtn:SetHighlight(FbcHighlight)
	end
	--arrowBtn:SetFrameLevel(arrowBtn:GetParent():GetFrameLevel() + 1)

	if not(arrowBtn.FlyoutListFrame) then
		arrowBtn.FlyoutListFrame = FlyoutListFrame_New(arrowBtn)
		arrowBtn:SetFrameRef("FlyoutListFrame_Ref", arrowBtn.FlyoutListFrame)
	end

	arrowBtn:SetAttribute("mouseoverincombat", FbcEnableMouseoverInCombat)

	arrowBtn:SetAttribute("_onclick", ArrowButtonOnClickSnippet)
	if FbcEnableMouseover then
		arrowBtn:SetAttribute("_onenter", ArrowButtonOnEnterSnippet)
	end
	arrowBtn:RegisterForClicks("LeftButtonUp", "RightButtonUp")

	--self, stateid, newstate
	arrowBtn:SetAttribute("_onstate-combat", ArrowButtonCombatSnippet)
	RegisterStateDriver(arrowBtn, "combat", "[nocombat] 0; [combat] 1;")

	arrowBtn:SetAttribute("_onstate-vehicle", ArrowButtonVehicleSnippet)
	RegisterStateDriver(arrowBtn, "vehicle", "[novehicleui] 0; [vehicleui] 1;")
	
	return arrowBtn
end

function GetFlyoutArrowButton(frame)
	if not(frame) or (frame:GetName() == "") then
		return nil
	end
	
	return FbcArrowButtons[frame:GetName()]
end

function FlyoutArrowButton_Attach(frame)
	if not(frame) or frame:GetName() == "" or InCombatLockdown() then
		if (frame.action and GetActionInfo(frame.action) == "flyout") or (frame._state_action and GetActionInfo(frame._state_action) == "flyout") then
			return
		end
	end
	
	local actnBtnName = frame:GetName()
	local currentSet = GetActiveTalentGroup()
	local expandDir = FBC_DIR_UP

	local arrowBtn = GetFlyoutArrowButton(frame)	
	if not(arrowBtn) then --create new
		arrowBtn = FlyoutArrowButton_New(frame)
	end
	local fbcs = FlyoutButtonCustom_Settings
	
	if fbcs["expandDir"][currentSet][actnBtnName] then
		expandDir = fbcs["expandDir"][currentSet][actnBtnName]
	elseif (frame:GetParent() == MultiBarRight or frame:GetParent() == MultiBarLeft) then
		expandDir = FBC_DIR_LEFT
	end
	arrowBtn:SetAnchor(frame, expandDir)
	arrowBtn:SetAttribute("expandDir", expandDir)
	
	local flf = arrowBtn.FlyoutListFrame
	flf:SetAnchor(arrowBtn, expandDir)

	if fbcs[actnBtnName] and fbcs[actnBtnName][currentSet] then
		for i, v in ipairs(fbcs[actnBtnName][currentSet]) do
			local btn = FlyoutListButton_AttachToList(flf, i, expandDir)
			if ACCEPTABLE_COMMANDS[v["command"]] then
				btn:Set(v["command"], v["value"], v["subValue"])
				btn:SetKey(v["keybind"])
			else
				btn:Set(nil, nil, nil)
				btn:SetKey(nil)
			end
		end
		arrowBtn:SetAttribute("bcount", #fbcs[actnBtnName][currentSet])
		arrowBtn:Show()
		arrowBtn:SetAlpha(1)
		arrowBtn.FlyoutArrow:Show()
	else
		arrowBtn:SetAttribute("bcount", 0)
		arrowBtn:Hide()
	end
	
	arrowBtn:SetFrameSize(expandDir)
	
	arrowBtn:SetAttribute("expanded", false)
	arrowBtn:SetTextureRotation(expandDir, false)
end

function FlyoutArrowButton:ShowArrow()
	if InCombatLockdown() then
		return
	end
	
	self:SetTextureRotation(self:GetAttribute("expandDir"), self:GetAttribute("expanded"))
	
	self:Show()
	self.FlyoutArrow:Show()
	if (self:GetAttribute("bcount") > 0) then
		self:SetAlpha(1)
	else
		self:SetAlpha(0.5)
	end
end

function FlyoutArrowButton:HideArrow()
	if InCombatLockdown() then
		return
	end
	
	if (self:GetAttribute("bcount") > 0) then
		self:SetAlpha(1)
	else
		self:SetAttribute("expanded", false)
		self.FlyoutListFrame:Hide()
		self.FlyoutArrow:Hide()
		self:Hide()
	end
end

function FlyoutArrowButton:UpdateArrow()
	if InCombatLockdown() or not(self:GetParent().customFlyout) then
		return
	end
	
	local currentSet = GetActiveTalentGroup()
	local actnBtnName = self:GetParent():GetName()
	local fbcs = FlyoutButtonCustom_Settings
	local count, settingsCount = 0, 0
	
	if fbcs[actnBtnName] and fbcs[actnBtnName][currentSet] then
		count, settingsCount = FlyoutButton_GetListButtonsCount(fbcs[actnBtnName][currentSet])
	else
		count, settingsCount = FlyoutButton_GetListButtonsCount(nil)
	end
	
	local flf = self.FlyoutListFrame
	flf:SetSize(self:GetAttribute("expandDir"), settingsCount)
	self:SetAttribute("bcount", count)
	self.FlyoutListFrame:SetAttribute("bcount", count)
	
	--cleanup
	for i, v in ipairs(flf.ButtonList) do
		if not(v.command) then
			if FbcSettingsMode then
				v:Set(nil, nil, nil)
				if i > count then
					v:HideButton()
				end
			else
				v:HideButton()
			end
		end
		v:SetAnchor(flf, i, self:GetAttribute("expandDir"))
	end
	
	--add empty buttons
	if FbcSettingsMode then
		for i = count + 1, settingsCount do
			local btn = FlyoutListButton_AttachToList(flf, i, self:GetAttribute("expandDir"))
			btn:Set(nil, nil, nil)
		end
	end
end

function FlyoutArrowButton:PostClick(button)
	if not(InCombatLockdown()) then
		if button == "LeftButton" then
			if FbcSettingsMode then
				self:UpdateArrow()
			else
				--cleanup
				for i, v in ipairs(self.FlyoutListFrame.ButtonList) do
					if v.command then
						v:Show()
					else
						v:HideButton()
					end
				end
				self.FlyoutListFrame:SetSize(self:GetAttribute("expandDir"), self:GetAttribute("bcount"))
			end
		elseif button == "RightButton" then
			local expandDir = self:GetAttribute("expandDir")
			expandDir = expandDir + 1
			if expandDir > FBC_DIR_RIGHT then
				expandDir = FBC_DIR_UP
			end

			local currentSet = GetActiveTalentGroup()
			FlyoutButtonCustom_Settings["expandDir"][currentSet][self:GetParent():GetName()] = expandDir

			self:SetAnchor(self:GetParent(), expandDir)
			self:SetFrameSize(expandDir)
			self:SetTextureRotation(expandDir, self:GetAttribute("expanded"))
			self:SetAttribute("expandDir", expandDir)

			self.FlyoutListFrame:SetAnchor(self, expandDir)
			--self.FlyoutListFrame:SetSize(expandDir, self:GetAttribute("bcount"))
			self:UpdateArrow()
		end
	end
end
